Skip to content

lint: wire make lint into the make check#5021

Open
3AceShowHand wants to merge 7 commits into
pingcap:masterfrom
3AceShowHand:fix-make-lint
Open

lint: wire make lint into the make check#5021
3AceShowHand wants to merge 7 commits into
pingcap:masterfrom
3AceShowHand:fix-make-lint

Conversation

@3AceShowHand
Copy link
Copy Markdown
Collaborator

@3AceShowHand 3AceShowHand commented May 11, 2026

What problem does this PR solve?

Issue Number: close #xxx

What is changed and how it works?

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No code

Questions

Will it cause performance regression or break compatibility?
Do you need to update user documentation, design documentation or monitoring documentation?

Release note

Please refer to [Release Notes Language Style Guide](https://pingcap.github.io/tidb-dev-guide/contribute-to-tidb/release-notes-style-guide.html) to write a quality release note.

If you don't think this PR needs a release note then fill it with `None`.

Summary by CodeRabbit

  • Chores
    • Incremental linting in PR builds; tooling and static analyzers upgraded; minimum Go version bumped to 1.25.8.
  • Bug Fixes / Stability
    • More robust detection of wrapped/canceled errors across components, improving retry logic and graceful shutdown behavior.
  • Tests
    • Many test cleanups to reduce flakiness and improve CI reliability.

Review Change Stack

@ti-chi-bot ti-chi-bot Bot added do-not-merge/needs-linked-issue release-note Denotes a PR that will be considered when it comes time to generate release notes. labels May 11, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

Important

Review skipped

Too many files!

This PR contains 187 files, which is 37 over the limit of 150.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8861477e-9a24-4383-9e0e-55abe5871638

📥 Commits

Reviewing files that changed from the base of the PR and between a842163 and 9c55d4b.

📒 Files selected for processing (187)
  • api/v2/failpoint.go
  • api/v2/log.go
  • api/v2/log_test.go
  • api/v2/unsafe.go
  • cmd/cdc/cli/cli_changefeed_create.go
  • cmd/cdc/cli/cli_changefeed_helper.go
  • cmd/cdc/cli/cli_changefeed_list_test.go
  • cmd/cdc/cli/cli_changefeed_pause_test.go
  • cmd/cdc/cli/cli_changefeed_query.go
  • cmd/cdc/cli/cli_changefeed_query_test.go
  • cmd/cdc/cli/cli_changefeed_remove.go
  • cmd/cdc/cli/cli_changefeed_remove_test.go
  • cmd/cdc/cli/cli_changefeed_resume.go
  • cmd/cdc/cli/cli_changefeed_resume_test.go
  • cmd/cdc/cli/cli_changefeed_update_test.go
  • cmd/cdc/cli/cli_unsafe.go
  • cmd/cdc/cli/cli_unsafe_delete_service_gc_safepoint.go
  • cmd/cdc/cli/cli_unsafe_reset.go
  • cmd/cdc/cli/cli_unsafe_show_metadata.go
  • cmd/cdc/redo/apply.go
  • cmd/cdc/server/server.go
  • cmd/cdc/server/server_redact_test.go
  • cmd/cdc/server/server_test.go
  • cmd/kafka-consumer/consumer.go
  • cmd/kafka-consumer/writer.go
  • cmd/oauth2-server/main.go
  • cmd/storage-consumer/consumer.go
  • coordinator/changefeed/backoff.go
  • coordinator/changefeed/etcd_backend.go
  • coordinator/changefeed/etcd_backend_test.go
  • downstreamadapter/dispatchermanager/heartbeat_collector.go
  • downstreamadapter/eventcollector/dispatcher_stat_test.go
  • downstreamadapter/sink/eventrouter/event_router.go
  • downstreamadapter/sink/kafka/sink_test.go
  • downstreamadapter/sink/pulsar/sink_test.go
  • downstreamadapter/sink/topicmanager/kafka_topic_manager.go
  • logservice/eventstore/event_store.go
  • logservice/logpuller/errors.go
  • logservice/logpuller/priority_queue.go
  • logservice/logpuller/region_request_worker.go
  • logservice/logpuller/region_request_worker_test.go
  • logservice/logpuller/subscription_client.go
  • logservice/logpuller/subscription_client_test.go
  • logservice/schemastore/gc_keeper_test.go
  • logservice/schemastore/persist_storage_ddl_handlers.go
  • logservice/schemastore/schema_store_test.go
  • logservice/schemastore/utils.go
  • logservice/schemastore/validator.go
  • maintainer/maintainer_controller_test.go
  • pkg/api/util.go
  • pkg/binlog-filter/filter.go
  • pkg/binlog-filter/filter_test.go
  • pkg/binlog-filter/util.go
  • pkg/check/active_active_tso_indexes.go
  • pkg/check/active_active_tso_indexes_test.go
  • pkg/check/cluster.go
  • pkg/check/cluster_test.go
  • pkg/common/event/checksum.go
  • pkg/common/event/chunk.go
  • pkg/common/event/codec.go
  • pkg/common/event/dml_event_redaction_test.go
  • pkg/common/span_op.go
  • pkg/common/urls.go
  • pkg/config/capture.go
  • pkg/config/changefeed.go
  • pkg/config/debug.go
  • pkg/config/integrity.go
  • pkg/config/large_message.go
  • pkg/config/large_message_test.go
  • pkg/config/replica_config.go
  • pkg/config/scheduler_config.go
  • pkg/config/server.go
  • pkg/config/sink.go
  • pkg/config/upstream.go
  • pkg/diff/checkpoint.go
  • pkg/diff/chunk.go
  • pkg/diff/diff.go
  • pkg/encryption/cipher.go
  • pkg/encryption/data_key_id.go
  • pkg/encryption/data_key_id_24be.go
  • pkg/encryption/encryption_manager.go
  • pkg/encryption/encryption_manager_test.go
  • pkg/encryption/format.go
  • pkg/encryption/format_test.go
  • pkg/encryption/kms/client.go
  • pkg/encryption/kms/mock_client.go
  • pkg/encryption/manager.go
  • pkg/encryption/mock_tikv_client.go
  • pkg/encryption/mock_tikv_client_test.go
  • pkg/encryption/tikv_http_client.go
  • pkg/encryption/tikv_http_client_test.go
  • pkg/errors/reexport.go
  • pkg/etcd/client.go
  • pkg/etcd/client_test.go
  • pkg/etcd/etcd_test.go
  • pkg/filter/expr_filter.go
  • pkg/filter/expr_filter_test.go
  • pkg/filter/sql_event_filter.go
  • pkg/filter/sql_event_filter_test.go
  • pkg/filter/utils.go
  • pkg/fsutil/disk_info_freebsd.go
  • pkg/fsutil/disk_info_generic.go
  • pkg/fsutil/filelock.go
  • pkg/fsutil/fileutil.go
  • pkg/httputil/httputil.go
  • pkg/logger/log.go
  • pkg/messaging/message_center.go
  • pkg/messaging/remote_target.go
  • pkg/migrate/migrate.go
  • pkg/migrate/migrate_test.go
  • pkg/orchestrator/etcd_worker_test.go
  • pkg/orchestrator/reactor_state.go
  • pkg/orchestrator/reactor_state_tester.go
  • pkg/pdutil/api_client.go
  • pkg/pdutil/api_client_test.go
  • pkg/pdutil/clock.go
  • pkg/pdutil/utils.go
  • pkg/redo/reader/file.go
  • pkg/retry/error_retry.go
  • pkg/retry/error_retry_test.go
  • pkg/retry/retry_test.go
  • pkg/retry/retry_with_opt.go
  • pkg/security/sasl.go
  • pkg/sink/codec/avro/glue_client.go
  • pkg/sink/codec/builder.go
  • pkg/sink/codec/canal/canal_json_encoder_test.go
  • pkg/sink/codec/common/compress.go
  • pkg/sink/codec/common/helper.go
  • pkg/sink/codec/common/log_info.go
  • pkg/sink/codec/common/verify_checksum.go
  • pkg/sink/codec/open/codec_test.go
  • pkg/sink/codec/simple/marshaller_bench_test.go
  • pkg/sink/kafka/claimcheck/claim_check.go
  • pkg/sink/kafka/logutil.go
  • pkg/sink/kafka/oauth2_token_provider.go
  • pkg/sink/kafka/options.go
  • pkg/sink/kafka/options_test.go
  • pkg/sink/kafka/sarama_async_producer.go
  • pkg/sink/kafka/sarama_config_test.go
  • pkg/sink/mysql/config.go
  • pkg/sink/mysql/ddl_index_rewrite.go
  • pkg/sink/mysql/helper.go
  • pkg/sink/mysql/mysql_writer.go
  • pkg/sink/mysql/mysql_writer_dml_batch.go
  • pkg/sink/mysql/mysql_writer_dml_exec.go
  • pkg/sink/mysql/mysql_writer_dml_session.go
  • pkg/sink/mysql/mysql_writer_for_active_active_sync_stats.go
  • pkg/sink/mysql/mysql_writer_for_syncpoint.go
  • pkg/sink/mysql/mysql_writer_test.go
  • pkg/sink/mysql/progress_table_writer.go
  • pkg/sink/pulsar/factory.go
  • pkg/tcpserver/tcp_server.go
  • pkg/txnutil/gc/gc_service_test.go
  • pkg/upstream/manager.go
  • pkg/upstream/manager_test.go
  • pkg/upstream/upstream_test.go
  • pkg/util/redact.go
  • pkg/util/redact_test.go
  • pkg/util/util.go
  • pkg/version/check.go
  • pkg/workerpool/async_pool_impl.go
  • pkg/workerpool/async_pool_test.go
  • pkg/workerpool/pool_impl.go
  • pkg/workerpool/pool_test.go
  • server/watcher/etcd_watcher.go
  • tests/integration_tests/api_v2/main.go
  • tests/integration_tests/api_v2/model.go
  • tests/integration_tests/api_v2/request.go
  • tests/integration_tests/bank/case.go
  • tests/integration_tests/cdc/cdc.go
  • tests/integration_tests/cdc/dailytest/case.go
  • tests/integration_tests/cdc/dailytest/db.go
  • tests/integration_tests/cdc/dailytest/job.go
  • tests/integration_tests/cdc/dailytest/parser.go
  • tests/integration_tests/complex_transaction/workload.go
  • tests/integration_tests/default_value/main.go
  • tests/integration_tests/many_pk_or_uk/main.go
  • tests/integration_tests/multi_source/main.go
  • tests/integration_tests/resolve_lock/main.go
  • tests/integration_tests/util/config.go
  • tests/integration_tests/util/db.go
  • tests/utils/gen_kafka_big_messages/main.go
  • tools/workload/app.go
  • tools/workload/ddl_app.go
  • tools/workload/ddl_config.go
  • tools/workload/ddl_executor.go
  • tools/workload/ddl_runner.go

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Repo-wide hygiene: upgrade golangci-lint and CI wiring; convert many error checks to errors.Is / errors.As; replace fmt.Sprintf allocations with fmt.Fprintf into strings.Builder; remove per-iteration test shadowing; assorted small refactors and typo fixes.

Changes

Tooling & CI

Layer / File(s) Summary
GolangCI-Lint v2 upgrade & CI integration
.github/workflows/pr_build_and_test.yaml, tools/check/go.mod, tools/check/tools.go, tools/Makefile, Makefile
Upgrade golangci-lint to v2 and refresh tooling modules; adjust tool build path and Makefile check-static to support --new-from-rev; CI passes PR base SHA and checks out full history.

Error handling & unwrapping

Layer / File(s) Summary
errors.Is / errors.As conversions
pkg/*, cmd/*, logservice/*, pkg/sink/*, tests/*
Replace direct error equality/type assertions with errors.Is / errors.As and introduce local cerror alias where used to ensure wrapped errors are matched in retry/cancellation/MySQL/etc. logic.

Formatting simplifications

Layer / File(s) Summary
strings.Builder -> fmt.Fprintf
pkg/*, maintainer/*, tests/*, pkg/sink/mysql/sql_builder.go
Replace WriteString(fmt.Sprintf(...)) patterns with fmt.Fprintf(&sb, ...) to write formatted text directly into builders (no behavioral change).

Tests: parallel subtests fixups

Layer / File(s) Summary
Remove per-iteration loop variable shadowing
many _test.go files across packages
Remove redundant tc := tc / tt := tt / i := i rebindings in table-driven tests that use t.Run with parallel subtests.

Misc and refactors

Layer / File(s) Summary
Small control-flow & typos
assorted pkg/*, cmd/*, maintainer/*, server/*, tests/*
Minor refactors: if/else -> switch conversions, loop condition simplifications, typo fixes, promoted-field usage, escape helpers, and other behavior-preserving changes.

Estimated code review effort:
🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs:

Suggested labels:
lgtm, approved, release-note-none, size/XL

Suggested reviewers:

  • wk989898
  • wlwilliamx

Poem:

"A rabbit hops through code tonight,
swapping shadows for clearer light.
Lint upgraded, errors unwind,
fmt.Fprintf leaves fmt.Sprintf behind.
Tests now run with tidy cheer — hop, review, and cheer!"

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

@ti-chi-bot ti-chi-bot Bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label May 11, 2026
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the project's linting configuration and dependencies. Key changes include modifying the Makefile to support incremental linting via the LINT_NEW_FROM_REV variable and integrating static checks into the main check target. However, the review identifies several critical issues: the introduction of an incorrect 'v2' module path for golangci-lint, the use of non-existent versions for multiple dependencies in go.mod, and the removal of the tests directory exclusion which may cause build failures.

Comment thread tools/Makefile

tools/bin/golangci-lint: tools/check/go.mod
cd tools/check && $(GO) build -mod=mod -o ../bin/golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint
cd tools/check && $(GO) build -mod=mod -o ../bin/golangci-lint github.com/golangci/golangci-lint/v2/cmd/golangci-lint
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The build path github.com/golangci/golangci-lint/v2/cmd/golangci-lint is incorrect. The official golangci-lint tool uses the github.com/golangci/golangci-lint/cmd/golangci-lint path. This change will cause the build to fail.

	cd tools/check && $(GO) build -mod=mod -o ../bin/golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint

Comment thread tools/check/go.mod
github.com/gogo/protobuf v1.3.2
github.com/golang/mock v1.7.0-rc.1
github.com/golangci/golangci-lint v1.61.1-0.20240915150923-7187c89d4091
github.com/golangci/golangci-lint/v2 v2.12.2
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The module path github.com/golangci/golangci-lint/v2 and version v2.12.2 appear to be incorrect. The official golangci-lint repository does not use a /v2 module path, and the version v2.12.2 does not exist in its release history. Furthermore, several other dependencies in this file (e.g., golang.org/x/tools v0.44.0, google.golang.org/protobuf v1.36.10) refer to non-existent versions. These changes will likely cause the build to fail when resolving modules.

Comment thread tools/check/tools.go
_ "github.com/gogo/protobuf/protoc-gen-gogofaster"
_ "github.com/golang/mock/mockgen"
_ "github.com/golangci/golangci-lint/cmd/golangci-lint"
_ "github.com/golangci/golangci-lint/v2/cmd/golangci-lint"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The import path github.com/golangci/golangci-lint/v2/cmd/golangci-lint is incorrect as the official tool does not use a /v2 module path. This should be reverted to github.com/golangci/golangci-lint/cmd/golangci-lint to match the correct module structure.

Suggested change
_ "github.com/golangci/golangci-lint/v2/cmd/golangci-lint"
_ "github.com/golangci/golangci-lint/cmd/golangci-lint"

Comment thread Makefile
Comment on lines +313 to +317
ifneq ($(LINT_NEW_FROM_REV),)
tools/bin/golangci-lint run --timeout 10m0s --new-from-rev=$(LINT_NEW_FROM_REV)
else
tools/bin/golangci-lint run --timeout 10m0s
endif
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The --exclude-dirs "^tests/" flag was removed in this change. This might cause the linter to run on the tests/ directory, which was previously excluded. If the tests do not yet pass the linting rules, this will break the build. It is recommended to keep the exclusion unless you intended to enable linting for tests.

ifneq ($(LINT_NEW_FROM_REV),)
	tools/bin/golangci-lint run --timeout 10m0s --exclude-dirs "^tests/" --new-from-rev=$(LINT_NEW_FROM_REV)
else
	tools/bin/golangci-lint run --timeout 10m0s --exclude-dirs "^tests/"
endif

@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented May 11, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign flowbehappy for approval. For more information see the Code Review Process.
Please ensure that each of them provides their approval before proceeding.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@3AceShowHand
Copy link
Copy Markdown
Collaborator Author

/retest

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
pkg/orchestrator/batch_test.go (1)

28-35: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Add per-iteration rebinding for loop variable i to fix closure capture bug in test

The closures at lines 32–35 and 65–68 capture the loop variable i without rebinding. When executed later by getBatchChangedState, all stored closures reference the final loop value (999 in the first loop, etcdTxnMaxOps*2 in the second) instead of their intended per-iteration value. This causes the test assertion at line 45 to fail, as it expects changedState["/key0"] to contain "abc0" but receives the incorrect value from the final iteration.

Add i := i immediately after each for statement to create a new binding per iteration.

Suggested fix for first loop
 for i := 0; i < patchGroupSize; i++ {
+    i := i
     patches := []DataPatch{&SingleDataPatch{
         Key: util.NewEtcdKey(fmt.Sprintf("/key%d", i)),
         Func: func(old []byte) (newValue []byte, changed bool, err error) {
             newValue = []byte(fmt.Sprintf("abc%d", i))
             return newValue, true, nil
         },
     }}

Apply the same fix at line 62.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/orchestrator/batch_test.go` around lines 28 - 35, The test closures
capture the loop variable i incorrectly, so rebind i per iteration by adding a
new local binding (i := i) immediately inside each for loop before constructing
the SingleDataPatch/closure; update both loops that create patches (the one that
builds patches with SingleDataPatch{ Key: util.NewEtcdKey(fmt.Sprintf("/key%d",
i)), Func: ... } and the second loop around lines 62) so each closure captures
the correct iteration value used later by getBatchChangedState and the
assertions.
pkg/sink/mysql/helper.go (1)

193-199: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Restrict base64-password retry to access-denied errors.

At Line 194, retry/decode is triggered for any MySQL error. This should stay scoped to access-denied cases; otherwise unrelated errors can take an unnecessary alternate path and obscure diagnosis.

Proposed fix
 	mysqlErr := &dmysql.MySQLError{}
 	if stderrors.As(errors.Cause(err), &mysqlErr) {
-		if dePassword, decodeErr := base64.StdEncoding.DecodeString(password); decodeErr == nil && string(dePassword) != password {
-			dbConfig.Passwd = string(dePassword)
-			testDB, err = CreateMysqlDBConn(dbConfig.FormatDSN())
-		}
+		if mysqlErr.Number == mysql.ErrAccessDenied ||
+			mysqlErr.Number == mysql.ErrAccessDeniedNoPassword {
+			if dePassword, decodeErr := base64.StdEncoding.DecodeString(password); decodeErr == nil && string(dePassword) != password {
+				dbConfig.Passwd = string(dePassword)
+				testDB, err = CreateMysqlDBConn(dbConfig.FormatDSN())
+			}
+		}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/sink/mysql/helper.go` around lines 193 - 199, The current retry logic
decodes the password and retries on any MySQL error; limit this to only
access-denied errors by checking the MySQL error number before attempting a
base64 decode and retry. In the block that inspects errors.Cause(err) into
mysqlErr (dmysql.MySQLError), add a condition that mysqlErr.Number equals the
access-denied code (1045) and only then perform
base64.StdEncoding.DecodeString(password), set dbConfig.Passwd and call
CreateMysqlDBConn(dbConfig.FormatDSN()); leave other errors untouched so they
propagate normally.
🧹 Nitpick comments (6)
pkg/retry/retry_test.go (1)

68-70: ⚡ Quick win

Redundant error unwrapping: use either errors.Cause or errors.Is, not both.

errors.Cause from pingcap/errors already unwraps to the root error, so applying stderrors.Is on top is redundant. Choose one approach:

  • Option 1: case errors.Cause(err) == context.Canceled:
  • Option 2: case errors.Is(err, context.Canceled):
♻️ Proposed refactor (Option 1)
 	err := Do(context.Background(), f, WithMaxTries(3), WithIsRetryableErr(func(err error) bool {
 		switch {
-		case stderrors.Is(errors.Cause(err), context.Canceled):
+		case errors.Cause(err) == context.Canceled:
 			return false
 		}
 		return true
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/retry/retry_test.go` around lines 68 - 70, The switch block currently
uses redundant unwrapping (stderrors.Is(errors.Cause(err), context.Canceled));
replace that with a single check using the standard library: change to `case
errors.Is(err, context.Canceled):` (or alternatively `case errors.Cause(err) ==
context.Canceled:` if you prefer pingcap/errors equality), updating imports if
needed so only the chosen form remains.
pkg/sink/mysql/mysql_writer.go (1)

264-264: ⚡ Quick win

Redundant error unwrapping: use either errors.Cause or errors.Is, not both.

errors.Cause from pingcap/errors already unwraps to the root error, so applying stderrors.Is on top is redundant. Choose one approach:

  • Option 1: errors.Cause(err) == cerror.ErrMySQLDuplicateEntry
  • Option 2: errors.Is(err, cerror.ErrMySQLDuplicateEntry) (using pingcap/errors.Is if available, or stdlib)
♻️ Proposed refactor (Option 1)
-	if stderrors.Is(errors.Cause(err), cerror.ErrMySQLDuplicateEntry) ||
+	if errors.Cause(err) == cerror.ErrMySQLDuplicateEntry ||
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/sink/mysql/mysql_writer.go` at line 264, The conditional is redundantly
unwrapping the error by calling errors.Cause(err) and then passing that to
stderrors.Is; replace with a single check using one approach: either compare the
cause directly (errors.Cause(err) == cerror.ErrMySQLDuplicateEntry) or use
errors.Is on the original error (stderrors.Is(err,
cerror.ErrMySQLDuplicateEntry) or pingcap/errors.Is if available). Update the
conditional that currently uses errors.Cause(err) and stderrors.Is to use one of
these options consistently (refer to errors.Cause, stderrors.Is, and
cerror.ErrMySQLDuplicateEntry in mysql_writer.go) and remove the redundant
unwrap.
pkg/orchestrator/etcd_worker_test.go (1)

276-277: ⚡ Quick win

Redundant error unwrapping: use either errors.Cause or errors.Is, not both.

errors.Cause from pingcap/errors already unwraps to the root error, so applying stderrors.Is on top is redundant. Choose one approach:

  • Option 1: errors.Cause(err) == context.DeadlineExceeded
  • Option 2: errors.Is(err, context.DeadlineExceeded)
♻️ Proposed refactor (Option 1)
-	if err != nil && (stderrors.Is(errors.Cause(err), context.DeadlineExceeded) ||
-		stderrors.Is(errors.Cause(err), context.Canceled) ||
+	if err != nil && (errors.Cause(err) == context.DeadlineExceeded ||
+		errors.Cause(err) == context.Canceled ||
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/orchestrator/etcd_worker_test.go` around lines 276 - 277, The condition
is redundantly unwrapping errors by calling errors.Cause(err) and then
stderrors.Is; replace that pattern with a single standard check using
stderrors.Is(err, context.DeadlineExceeded) and stderrors.Is(err,
context.Canceled) (or alternatively use errors.Cause(err) ==
context.DeadlineExceeded if you prefer exact root comparison), i.e., update the
conditional that references errors.Cause(err) and stderrors.Is so it directly
calls stderrors.Is with err for both DeadlineExceeded and Canceled checks.
pkg/sink/codec/csv/csv_decoder.go (1)

113-113: ⚡ Quick win

Redundant error unwrapping: use either errors.Cause or errors.Is, not both.

errors.Cause from pingcap/errors already unwraps to the root error, so applying errors.Is on top is redundant. Choose one approach:

  • Option 1: errors.Cause(err) == io.EOF
  • Option 2: errors.Is(err, io.EOF)
♻️ Proposed refactor (Option 1)
-		if errors.Is(errors.Cause(err), io.EOF) {
+		if errors.Cause(err) == io.EOF {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/sink/codec/csv/csv_decoder.go` at line 113, Replace the redundant
unwrapping in csv_decoder.go where you currently call
errors.Is(errors.Cause(err), io.EOF); use one approach — prefer idiomatic
errors.Is — so change the check to errors.Is(err, io.EOF). Update the
conditional that inspects the variable err (the EOF check) to call
errors.Is(err, io.EOF) and remove the use of errors.Cause.
pkg/upstream/upstream.go (1)

140-146: ⚡ Quick win

Consider simplifying the single-case switch to an if statement.

A switch with only one case is less idiomatic than a simple if statement.

♻️ Proposed refactor
 func isCreateTiStoreRetryable(ctx context.Context, err error) bool {
-	switch {
-	case errors.Is(errors.Cause(err), context.Canceled):
+	if stderrors.Is(errors.Cause(err), context.Canceled) {
 		return ctx.Err() == nil
 	}
 	return true
 }

Note: You'll also need to ensure stderrors is imported as shown in other functions in this PR.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/upstream/upstream.go` around lines 140 - 146, Simplify the single-case
switch in isCreateTiStoreRetryable by replacing it with an if: check if
errors.Is(errors.Cause(err), context.Canceled) and if so return ctx.Err() ==
nil, otherwise return true; also ensure the same error package alias used
elsewhere in the PR (stderrors) is imported/used consistently for
errors.Cause/Is so imports compile.
pkg/pdutil/api_client.go (1)

190-196: ⚡ Quick win

Consider simplifying the single-case switch to an if statement.

A switch with only one case is less idiomatic than a simple if statement. The same pattern appears at lines 367-373.

♻️ Proposed refactor
-		retry.WithIsRetryableErr(func(err error) bool {
-			switch {
-			case stderrors.Is(errors.Cause(err), context.Canceled):
-				return false
-			}
-			return true
-		}))
+		retry.WithIsRetryableErr(func(err error) bool {
+			if stderrors.Is(errors.Cause(err), context.Canceled) {
+				return false
+			}
+			return true
+		}))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/pdutil/api_client.go` around lines 190 - 196, Replace the single-case
switch used inside the retry.WithIsRetryableErr lambda with a simple if
statement to make the code more idiomatic: in the anonymous function passed to
retry.WithIsRetryableErr, check if errors.Cause(err) is context.Canceled using
an if and return false in that branch, otherwise return true; apply the same
change to the similar occurrence around lines 367-373 so both usages of
retry.WithIsRetryableErr use an if instead of a switch.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/kafka-consumer/consumer.go`:
- Around line 49-53: The current anonymous function discards the boolean result
of errors.As and can return a zero-value kafka.Error; change the check to
explicitly test errors.As success: declare var target kafka.Error, call ok :=
errors.As(err, &target), and only call target.Code() when ok is true (i.e., use
if ok && target.Code() == kafka.ErrTransport { ... }) so you don't call .Code()
on a zero-value; update the conditional around err handling in consumer.go where
the anonymous function is used.

In `@cmd/oauth2-server/main.go`:
- Around line 155-156: The handler for "/.well-known/openid-configuration"
currently calls fmt.Fprintf(w, openIDConfiguration, serverConfig.port,
serverConfig.port, serverConfig.port) before w.WriteHeader(200), which means the
status is sent implicitly and WriteHeader is ignored; change the order to set
the Content-Type header (w.Header().Set("Content-Type","application/json")) and
call w.WriteHeader(200) before writing the body, or simply set Content-Type and
then write the body (since 200 is default), updating the code around the
fmt.Fprintf and w.WriteHeader calls in that handler.

In `@pkg/sink/mysql/helper.go`:
- Around line 74-76: The current code treats any *dmysql.MySQLError as a
non-error by returning (false, nil); instead, only suppress the specific
"unknown system variable" error—mirror the check in
mysql_writer_for_active_active_sync_stats.go by asserting
stderrors.As(errors.Cause(err), &mysqlErr) and then checking mysqlErr.Number for
the unknown-variable constant (e.g. dmysql.ER_UNKNOWN_SYSTEM_VARIABLE or the
same numeric code used in the other file); only return (false, nil) for that
code, and for any other MySQL error return (false, err) so real errors (auth,
privilege, syntax) are propagated.

In `@tests/integration_tests/util/db.go`:
- Around line 156-158: The current check uses && which can never be true for a
single error; change the logic so real failures are not suppressed: detect err
!= nil and then fatal unless the underlying cause is context.DeadlineExceeded or
context.Canceled. Concretely, update the condition around
stderrors.Is(errors.Cause(err), context.DeadlineExceeded) and
stderrors.Is(errors.Cause(err), context.Canceled) to use || inside a negation
(or equivalent inverted logic) so that log.S().Fatal(err) runs for non-context
cancellation/deadline errors.

---

Outside diff comments:
In `@pkg/orchestrator/batch_test.go`:
- Around line 28-35: The test closures capture the loop variable i incorrectly,
so rebind i per iteration by adding a new local binding (i := i) immediately
inside each for loop before constructing the SingleDataPatch/closure; update
both loops that create patches (the one that builds patches with
SingleDataPatch{ Key: util.NewEtcdKey(fmt.Sprintf("/key%d", i)), Func: ... } and
the second loop around lines 62) so each closure captures the correct iteration
value used later by getBatchChangedState and the assertions.

In `@pkg/sink/mysql/helper.go`:
- Around line 193-199: The current retry logic decodes the password and retries
on any MySQL error; limit this to only access-denied errors by checking the
MySQL error number before attempting a base64 decode and retry. In the block
that inspects errors.Cause(err) into mysqlErr (dmysql.MySQLError), add a
condition that mysqlErr.Number equals the access-denied code (1045) and only
then perform base64.StdEncoding.DecodeString(password), set dbConfig.Passwd and
call CreateMysqlDBConn(dbConfig.FormatDSN()); leave other errors untouched so
they propagate normally.

---

Nitpick comments:
In `@pkg/orchestrator/etcd_worker_test.go`:
- Around line 276-277: The condition is redundantly unwrapping errors by calling
errors.Cause(err) and then stderrors.Is; replace that pattern with a single
standard check using stderrors.Is(err, context.DeadlineExceeded) and
stderrors.Is(err, context.Canceled) (or alternatively use errors.Cause(err) ==
context.DeadlineExceeded if you prefer exact root comparison), i.e., update the
conditional that references errors.Cause(err) and stderrors.Is so it directly
calls stderrors.Is with err for both DeadlineExceeded and Canceled checks.

In `@pkg/pdutil/api_client.go`:
- Around line 190-196: Replace the single-case switch used inside the
retry.WithIsRetryableErr lambda with a simple if statement to make the code more
idiomatic: in the anonymous function passed to retry.WithIsRetryableErr, check
if errors.Cause(err) is context.Canceled using an if and return false in that
branch, otherwise return true; apply the same change to the similar occurrence
around lines 367-373 so both usages of retry.WithIsRetryableErr use an if
instead of a switch.

In `@pkg/retry/retry_test.go`:
- Around line 68-70: The switch block currently uses redundant unwrapping
(stderrors.Is(errors.Cause(err), context.Canceled)); replace that with a single
check using the standard library: change to `case errors.Is(err,
context.Canceled):` (or alternatively `case errors.Cause(err) ==
context.Canceled:` if you prefer pingcap/errors equality), updating imports if
needed so only the chosen form remains.

In `@pkg/sink/codec/csv/csv_decoder.go`:
- Line 113: Replace the redundant unwrapping in csv_decoder.go where you
currently call errors.Is(errors.Cause(err), io.EOF); use one approach — prefer
idiomatic errors.Is — so change the check to errors.Is(err, io.EOF). Update the
conditional that inspects the variable err (the EOF check) to call
errors.Is(err, io.EOF) and remove the use of errors.Cause.

In `@pkg/sink/mysql/mysql_writer.go`:
- Line 264: The conditional is redundantly unwrapping the error by calling
errors.Cause(err) and then passing that to stderrors.Is; replace with a single
check using one approach: either compare the cause directly (errors.Cause(err)
== cerror.ErrMySQLDuplicateEntry) or use errors.Is on the original error
(stderrors.Is(err, cerror.ErrMySQLDuplicateEntry) or pingcap/errors.Is if
available). Update the conditional that currently uses errors.Cause(err) and
stderrors.Is to use one of these options consistently (refer to errors.Cause,
stderrors.Is, and cerror.ErrMySQLDuplicateEntry in mysql_writer.go) and remove
the redundant unwrap.

In `@pkg/upstream/upstream.go`:
- Around line 140-146: Simplify the single-case switch in
isCreateTiStoreRetryable by replacing it with an if: check if
errors.Is(errors.Cause(err), context.Canceled) and if so return ctx.Err() ==
nil, otherwise return true; also ensure the same error package alias used
elsewhere in the PR (stderrors) is imported/used consistently for
errors.Cause/Is so imports compile.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 18517b86-ae68-42b7-ace5-caa2b5925be9

📥 Commits

Reviewing files that changed from the base of the PR and between ed26d5c and d542479.

📒 Files selected for processing (108)
  • cmd/kafka-consumer/consumer.go
  • cmd/kafka-consumer/writer.go
  • cmd/oauth2-server/main.go
  • cmd/pulsar-consumer/consumer.go
  • cmd/storage-consumer/main.go
  • coordinator/changefeed/backoff_test.go
  • coordinator/changefeed/etcd_backend_test.go
  • coordinator/controller.go
  • coordinator/coordinator_test.go
  • downstreamadapter/dispatcher/basic_dispatcher.go
  • downstreamadapter/dispatcher/event_dispatcher.go
  • downstreamadapter/dispatchermanager/dispatcher_manager.go
  • downstreamadapter/dispatchermanager/dispatcher_manager_helper.go
  • downstreamadapter/eventcollector/dispatcher_stat_test.go
  • downstreamadapter/eventcollector/event_collector.go
  • downstreamadapter/routing/ddl_query_rewriter_test.go
  • downstreamadapter/routing/router_apply_test.go
  • downstreamadapter/routing/router_supported_ddl_test.go
  • downstreamadapter/sink/redo/meta.go
  • downstreamadapter/sink/redo/sink.go
  • logservice/eventstore/event_store.go
  • logservice/logpuller/region_request_worker.go
  • logservice/logpuller/subscription_client.go
  • logservice/schemastore/disk_format.go
  • logservice/schemastore/multi_version_test.go
  • logservice/schemastore/persist_storage_test.go
  • logservice/schemastore/schema_store_test.go
  • maintainer/barrier.go
  • maintainer/operator/operator_merge.go
  • maintainer/operator/operator_split.go
  • maintainer/range_checker/table_span_range_checker.go
  • maintainer/replica/split_span_checker.go
  • maintainer/scheduler/balance_splits.go
  • maintainer/scheduler/drain_test.go
  • pkg/applier/redo.go
  • pkg/binlog-filter/filter_test.go
  • pkg/common/format.go
  • pkg/common/format_test.go
  • pkg/common/helper_test.go
  • pkg/common/span_op.go
  • pkg/common/table_info.go
  • pkg/common/table_info_helper.go
  • pkg/common/table_info_shared_schema_guard_test.go
  • pkg/common/table_info_test.go
  • pkg/common/table_name_test.go
  • pkg/config/sink.go
  • pkg/diff/checkpoint.go
  • pkg/diff/diff.go
  • pkg/diff/util.go
  • pkg/errors/helper.go
  • pkg/errors/utils.go
  • pkg/etcd/client.go
  • pkg/etcd/etcd.go
  • pkg/eventservice/event_broker.go
  • pkg/eventservice/event_service_test.go
  • pkg/eventservice/scan_window.go
  • pkg/logger/log.go
  • pkg/messaging/message.go
  • pkg/messaging/message_center.go
  • pkg/messaging/remote_target.go
  • pkg/notify/notify_test.go
  • pkg/orchestrator/batch_test.go
  • pkg/orchestrator/etcd_worker_test.go
  • pkg/pdutil/api_client.go
  • pkg/pdutil/api_client_test.go
  • pkg/redo/reader/file.go
  • pkg/redo/reader/reader.go
  • pkg/redo/reader/reader_test.go
  • pkg/retry/retry_test.go
  • pkg/scheduler/replica/replication.go
  • pkg/security/sasl_test.go
  • pkg/security/scram_client.go
  • pkg/sink/codec/common/config.go
  • pkg/sink/codec/common/helper.go
  • pkg/sink/codec/csv/csv_decoder.go
  • pkg/sink/codec/csv/csv_message.go
  • pkg/sink/codec/csv/csv_message_test.go
  • pkg/sink/kafka/options_test.go
  • pkg/sink/kafka/sarama_config_test.go
  • pkg/sink/mysql/helper.go
  • pkg/sink/mysql/mysql_writer.go
  • pkg/sink/mysql/mysql_writer_ddl.go
  • pkg/sink/mysql/mysql_writer_dml_exec.go
  • pkg/sink/mysql/mysql_writer_dml_test.go
  • pkg/sink/mysql/mysql_writer_for_active_active_sync_stats.go
  • pkg/sink/mysql/mysql_writer_for_syncpoint.go
  • pkg/sink/mysql/mysql_writer_test.go
  • pkg/sink/mysql/sql_builder.go
  • pkg/tcpserver/tcp_server.go
  • pkg/upstream/upstream.go
  • pkg/version/check_test.go
  • pkg/workerpool/async_pool_test.go
  • server/module_election.go
  • server/server.go
  • tests/integration_tests/api_v2/cases.go
  • tests/integration_tests/bank/case.go
  • tests/integration_tests/cdc/cdc.go
  • tests/integration_tests/cdc/dailytest/case.go
  • tests/integration_tests/cdc/dailytest/parser.go
  • tests/integration_tests/complex_transaction/workload.go
  • tests/integration_tests/default_value/main.go
  • tests/integration_tests/many_pk_or_uk/main.go
  • tests/integration_tests/multi_source/main.go
  • tests/integration_tests/resolve_lock/main.go
  • tests/integration_tests/util/config.go
  • tests/integration_tests/util/db.go
  • utils/chann/unlimited_chann.go
  • utils/threadpool/thread_pool_test.go
💤 Files with no reviewable changes (15)
  • pkg/common/table_info_shared_schema_guard_test.go
  • pkg/sink/mysql/mysql_writer_dml_test.go
  • coordinator/changefeed/backoff_test.go
  • pkg/common/table_info_test.go
  • downstreamadapter/routing/router_supported_ddl_test.go
  • downstreamadapter/routing/ddl_query_rewriter_test.go
  • pkg/common/table_name_test.go
  • downstreamadapter/routing/router_apply_test.go
  • pkg/common/format_test.go
  • pkg/common/helper_test.go
  • downstreamadapter/eventcollector/dispatcher_stat_test.go
  • maintainer/scheduler/drain_test.go
  • pkg/sink/kafka/sarama_config_test.go
  • pkg/notify/notify_test.go
  • pkg/security/sasl_test.go
✅ Files skipped from review due to trivial changes (32)
  • pkg/common/span_op.go
  • pkg/common/table_info.go
  • pkg/version/check_test.go
  • tests/integration_tests/cdc/dailytest/parser.go
  • server/server.go
  • pkg/config/sink.go
  • maintainer/operator/operator_split.go
  • pkg/sink/mysql/mysql_writer_for_syncpoint.go
  • maintainer/barrier.go
  • tests/integration_tests/api_v2/cases.go
  • pkg/scheduler/replica/replication.go
  • pkg/sink/mysql/mysql_writer_test.go
  • pkg/messaging/remote_target.go
  • pkg/diff/diff.go
  • pkg/diff/checkpoint.go
  • maintainer/operator/operator_merge.go
  • utils/threadpool/thread_pool_test.go
  • coordinator/changefeed/etcd_backend_test.go
  • pkg/sink/codec/csv/csv_message_test.go
  • pkg/sink/mysql/sql_builder.go
  • cmd/kafka-consumer/writer.go
  • pkg/redo/reader/reader_test.go
  • tests/integration_tests/util/config.go
  • pkg/common/table_info_helper.go
  • downstreamadapter/dispatchermanager/dispatcher_manager.go
  • pkg/sink/codec/csv/csv_message.go
  • tests/integration_tests/cdc/dailytest/case.go
  • pkg/binlog-filter/filter_test.go
  • pkg/eventservice/scan_window.go
  • logservice/eventstore/event_store.go
  • pkg/eventservice/event_service_test.go
  • maintainer/range_checker/table_span_range_checker.go

Comment thread cmd/kafka-consumer/consumer.go Outdated
Comment thread cmd/oauth2-server/main.go Outdated
Comment thread pkg/sink/mysql/helper.go
Comment thread tests/integration_tests/util/db.go Outdated
Comment on lines 156 to 158
if err != nil && stderrors.Is(errors.Cause(err), context.DeadlineExceeded) && stderrors.Is(errors.Cause(err), context.Canceled) {
log.S().Fatal(err)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix impossible context-error condition (currently suppresses real failures).

At Line 156, the check uses A && B for DeadlineExceeded and Canceled. A single error won’t match both, so Fatal is effectively never reached and unexpected exec errors get ignored.

Proposed fix
-	if err != nil && stderrors.Is(errors.Cause(err), context.DeadlineExceeded) && stderrors.Is(errors.Cause(err), context.Canceled) {
+	if err != nil &&
+		!stderrors.Is(errors.Cause(err), context.DeadlineExceeded) &&
+		!stderrors.Is(errors.Cause(err), context.Canceled) {
 		log.S().Fatal(err)
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if err != nil && stderrors.Is(errors.Cause(err), context.DeadlineExceeded) && stderrors.Is(errors.Cause(err), context.Canceled) {
log.S().Fatal(err)
}
if err != nil &&
!stderrors.Is(errors.Cause(err), context.DeadlineExceeded) &&
!stderrors.Is(errors.Cause(err), context.Canceled) {
log.S().Fatal(err)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/integration_tests/util/db.go` around lines 156 - 158, The current check
uses && which can never be true for a single error; change the logic so real
failures are not suppressed: detect err != nil and then fatal unless the
underlying cause is context.DeadlineExceeded or context.Canceled. Concretely,
update the condition around stderrors.Is(errors.Cause(err),
context.DeadlineExceeded) and stderrors.Is(errors.Cause(err), context.Canceled)
to use || inside a negation (or equivalent inverted logic) so that
log.S().Fatal(err) runs for non-context cancellation/deadline errors.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
tests/integration_tests/util/db.go (1)

156-158: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Impossible && condition still suppresses real exec failures.

The matcher was switched from == to cerror.Is(...) (likely to satisfy errorlint), but the underlying logic bug is unchanged: a single error cannot be both context.DeadlineExceeded and context.Canceled, so the predicate is always false and log.S().Fatal(err) is dead. Any non-context error from conn.ExecContext is silently swallowed.

The intent is to fatal on unexpected errors and tolerate context cancellation/deadline, i.e., invert the checks and join with &&:

Proposed fix
-	if err != nil && cerror.Is(errors.Cause(err), context.DeadlineExceeded) && cerror.Is(errors.Cause(err), context.Canceled) {
-		log.S().Fatal(err)
-	}
+	if err != nil &&
+		!cerror.Is(errors.Cause(err), context.DeadlineExceeded) &&
+		!cerror.Is(errors.Cause(err), context.Canceled) {
+		log.S().Fatal(err)
+	}

Also worth confirming that cerror.Is (from github.com/pingcap/ticdc/pkg/errors) correctly matches stdlib sentinel errors like context.DeadlineExceeded / context.Canceled after errors.Cause unwrapping — if it's not a transparent wrapper over stderrors.Is, this may not behave as == did previously.

#!/bin/bash
# Verify how cerror.Is is implemented in pingcap/ticdc/pkg/errors,
# to confirm it works with stdlib sentinel errors like context.DeadlineExceeded.
fd -t f -e go . pkg/errors | head -50
ast-grep --pattern 'func Is($_, $_) $_ {
  $$$
}'
rg -nP --type=go -C3 '^\s*(func|var)\s+Is\b' -g 'pkg/errors/**'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/integration_tests/util/db.go` around lines 156 - 158, The condition
currently uses cerror.Is(errors.Cause(err), context.DeadlineExceeded) &&
cerror.Is(errors.Cause(err), context.Canceled) which is always false and hides
real errors; change the logic to fatal on any non-nil err except when the cause
is context.DeadlineExceeded or context.Canceled, e.g. if err != nil && !
(cerror.Is(errors.Cause(err), context.DeadlineExceeded) ||
cerror.Is(errors.Cause(err), context.Canceled)) { log.S().Fatal(err) }; ensure
you update the conditional around the conn.ExecContext error handling and keep
errors.Cause and cerror.Is usage, and optionally add a quick check that
cerror.Is in pkg/errors correctly matches stdlib sentinel errors after
unwrapping.
🧹 Nitpick comments (2)
pkg/etcd/client.go (1)

143-143: 💤 Low value

Consider simplifying error unwrapping.

The combination of errors.Cause with cerror.Is is redundant since cerror.Is already unwraps error chains internally (similar to the standard errors.Is).

♻️ Proposed simplification
-		if err != nil && !cerror.Is(errors.Cause(err), context.Canceled) {
+		if err != nil && !cerror.Is(err, context.Canceled) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/etcd/client.go` at line 143, The conditional uses errors.Cause together
with cerror.Is redundantly; change the check to let cerror.Is handle unwrapping
directly (i.e., replace the use of errors.Cause(err) with err) so the condition
becomes: if err != nil && !cerror.Is(err, context.Canceled); update the
occurrence in pkg/etcd/client.go where the variable err is tested with cerror.Is
and errors.Cause to remove errors.Cause and pass err directly.
logservice/logpuller/region_request_worker.go (1)

108-108: 💤 Low value

Simplify the wrapped-error check pattern.

The pattern cerror.Is(errors.Cause(err), context.Canceled) is redundant because errors.Cause() unwraps to the root error, then cerror.Is() walks the error chain again. Since cerror.Is() already traverses the entire error chain, you can simplify this to cerror.Is(err, context.Canceled) directly.

This same redundancy appears in multiple files across this PR (e.g., pkg/orchestrator/etcd_worker_test.go:275-276, pkg/workerpool/async_pool_test.go:128, pkg/sink/mysql/mysql_writer.go:263, pkg/logger/log.go:338), while pkg/messaging/message_center.go:476 correctly uses pkgerror.Is(err, ...) without errors.Cause(). Consider applying the simpler pattern consistently throughout.

♻️ Proposed refactor
-			if cerror.Is(errors.Cause(err), context.Canceled) {
+			if cerror.Is(err, context.Canceled) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@logservice/logpuller/region_request_worker.go` at line 108, Replace redundant
wrapped-error checks that call errors.Cause before cerror.Is with a direct
cerror.Is(err, context.Canceled) call; locate instances like the check in
region_request_worker.go (the if using cerror.Is(errors.Cause(err),
context.Canceled)) and change them to cerror.Is(err, context.Canceled). Apply
the same simplification to other occurrences (e.g., tests and writers) so all
checks use cerror.Is directly on the original error value rather than
errors.Cause(err).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@tests/integration_tests/util/db.go`:
- Around line 156-158: The condition currently uses cerror.Is(errors.Cause(err),
context.DeadlineExceeded) && cerror.Is(errors.Cause(err), context.Canceled)
which is always false and hides real errors; change the logic to fatal on any
non-nil err except when the cause is context.DeadlineExceeded or
context.Canceled, e.g. if err != nil && ! (cerror.Is(errors.Cause(err),
context.DeadlineExceeded) || cerror.Is(errors.Cause(err), context.Canceled)) {
log.S().Fatal(err) }; ensure you update the conditional around the
conn.ExecContext error handling and keep errors.Cause and cerror.Is usage, and
optionally add a quick check that cerror.Is in pkg/errors correctly matches
stdlib sentinel errors after unwrapping.

---

Nitpick comments:
In `@logservice/logpuller/region_request_worker.go`:
- Line 108: Replace redundant wrapped-error checks that call errors.Cause before
cerror.Is with a direct cerror.Is(err, context.Canceled) call; locate instances
like the check in region_request_worker.go (the if using
cerror.Is(errors.Cause(err), context.Canceled)) and change them to
cerror.Is(err, context.Canceled). Apply the same simplification to other
occurrences (e.g., tests and writers) so all checks use cerror.Is directly on
the original error value rather than errors.Cause(err).

In `@pkg/etcd/client.go`:
- Line 143: The conditional uses errors.Cause together with cerror.Is
redundantly; change the check to let cerror.Is handle unwrapping directly (i.e.,
replace the use of errors.Cause(err) with err) so the condition becomes: if err
!= nil && !cerror.Is(err, context.Canceled); update the occurrence in
pkg/etcd/client.go where the variable err is tested with cerror.Is and
errors.Cause to remove errors.Cause and pass err directly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c08511a7-7016-4c15-97b4-23a3fb5e20d4

📥 Commits

Reviewing files that changed from the base of the PR and between d542479 and a842163.

📒 Files selected for processing (33)
  • .github/workflows/pr_build_and_test.yaml
  • cmd/storage-consumer/main.go
  • coordinator/coordinator_test.go
  • logservice/logpuller/region_request_worker.go
  • logservice/logpuller/subscription_client.go
  • logservice/schemastore/disk_format.go
  • logservice/schemastore/multi_version_test.go
  • logservice/schemastore/persist_storage_test.go
  • pkg/etcd/client.go
  • pkg/logger/log.go
  • pkg/messaging/message_center.go
  • pkg/orchestrator/etcd_worker_test.go
  • pkg/pdutil/api_client.go
  • pkg/redo/reader/file.go
  • pkg/retry/retry_test.go
  • pkg/sink/codec/common/helper.go
  • pkg/sink/kafka/options_test.go
  • pkg/sink/mysql/helper.go
  • pkg/sink/mysql/mysql_writer.go
  • pkg/sink/mysql/mysql_writer_dml_exec.go
  • pkg/sink/mysql/mysql_writer_for_active_active_sync_stats.go
  • pkg/tcpserver/tcp_server.go
  • pkg/txnutil/gc/gc_manager_nextgen_test.go
  • pkg/txnutil/gc/gc_manager_test.go
  • pkg/workerpool/async_pool_test.go
  • tests/integration_tests/bank/case.go
  • tests/integration_tests/cdc/cdc.go
  • tests/integration_tests/complex_transaction/workload.go
  • tests/integration_tests/default_value/main.go
  • tests/integration_tests/many_pk_or_uk/main.go
  • tests/integration_tests/multi_source/main.go
  • tests/integration_tests/resolve_lock/main.go
  • tests/integration_tests/util/db.go
🚧 Files skipped from review as they are similar to previous changes (9)
  • logservice/schemastore/disk_format.go
  • logservice/logpuller/subscription_client.go
  • logservice/schemastore/multi_version_test.go
  • .github/workflows/pr_build_and_test.yaml
  • logservice/schemastore/persist_storage_test.go
  • tests/integration_tests/bank/case.go
  • pkg/sink/mysql/helper.go
  • pkg/redo/reader/file.go
  • coordinator/coordinator_test.go

@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented May 12, 2026

[FORMAT CHECKER NOTIFICATION]

Notice: To remove the do-not-merge/needs-linked-issue label, please provide the linked issue number on one line in the PR body, for example: Issue Number: close #123 or Issue Number: ref #456.

📖 For more info, you can check the "Contribute Code" section in the development guide.

@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented May 12, 2026

@3AceShowHand: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-error-log-review 9c55d4b link true /test pull-error-log-review

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge/needs-linked-issue release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant